<?php
declare (strict_types = 1);

namespace app\product\controller;

use app\common\upload\Excel;
use app\common\util\ApiUtil;
use app\product\BaseController;
use app\product\service\CategoryLinkService;
use app\product\service\CategoryService;
use app\product\service\ProductService;
use app\product\service\ProductSkuService;
use think\facade\Db;
use think\Request;

class ProductController extends BaseController
{
    public function __construct(ProductService $productService,
                                ProductSkuService $productSkuService,
                                CategoryLinkService $productCategoryLinkService,
                                CategoryService $categoryService)
    {
        $this->productService = $productService;
        $this->productSkuService = $productSkuService;
        $this->categoryService = $categoryService;
        $this->productCategoryLinkService = $productCategoryLinkService;
    }

    public function list(){
        $params = request()->param();
        $limit = array();
        $limit['page'] = !empty($params['page'])?intval($params['page']):1;
        $limit['pagesize'] = !empty($params['pagesize'])?intval($params['pagesize']):10;
        $where = $this->productService->search($params);
        $total = $this->productService->count($where);
        $list = $this->productService->list($where , $limit);
        return ApiUtil::normal(['total'=>$total,'list'=>$list]);
    }

    public function find(){
        $id = input('id',0);
        if(!$id) return ApiUtil::normal(null, 'ID不能为空', ApiUtil::CODE_FAIL);
        $find = $this->productService->find(['id'=>$id]);
        return ApiUtil::normal($find);
    }

    public function add(){
        $params = request()->param();
        $params['sku'] = !empty($params['sku'])?trim($params['sku']):$this->productSkuService->get_product_sku();
        $data = $this->productService->verify($params);
        if(is_string($data)) return ApiUtil::normal(null, $data, ApiUtil::CODE_FAIL);
        $variants = $params['variants']??'';
        DB::startTrans();
        try{
            $lastId = $this->productService->insertGetId($data);
            if(!$lastId) ApiUtil::abort('产品添加失败');
            // 变体处理
            if(!empty($variants) && $variants!='[]') $this->productService->addSkus(intval($lastId),$variants,$data['sku']);
            // 多个分类ID，另外存一个表
            $cates = explode(',', $data['category_id']);
            $multiple_cate = array();
            foreach ($cates as $k => $v) {
                $multiple_cate[$k]['product_id'] = $lastId;
                $multiple_cate[$k]['cate_id'] = $v;
            }
            $in_mul_cate = $this->productCategoryLinkService->insertAll($multiple_cate);
            if(!$in_mul_cate) ApiUtil::abort( '插入多分类失败');
            DB::commit();
            return ApiUtil::normal( ['id'=>$lastId]);
        }catch (\Exception $e){
            DB::rollBack();
            return ApiUtil::excep($e);
        }
    }

    public function edit(){
        $params = request()->param();
        $id = intval($params['id'])??0;
        if(empty($id)) return ApiUtil::normal(null, 'ID不能为空', ApiUtil::CODE_FAIL);
        $data = $this->productService->verify($params,$id);
        if(is_string($data)) return ApiUtil::normal(null, $data, ApiUtil::CODE_FAIL);
        $variants = $params['variants']??'';
        DB::startTrans();
        try{
            // 变体处理
            if(!empty($variants)){
                $this->productService->delSkus($params['id']);
                if($variants!='[]') $this->productService->addSkus(intval($params['id']),$variants,$data['sku']);
            }
            // 编辑分类前先删除，再插入
            $this->productCategoryLinkService->delete(['product_id',$params['id']]);
            // 多个分类ID，另外存一个表
            $cates = explode(',', $params['category_id']);
            $multiple_cate = array();
            foreach ($cates as $k => $v) {
                $multiple_cate[$k]['product_id'] = $params['id'];
                $multiple_cate[$k]['cate_id'] = $v;
            }
            $in_mul_cate = $this->productCategoryLinkService->insertAll($multiple_cate);
            if(!$in_mul_cate) ApiUtil::abort( '插入多分类失败');
            $update = $this->productService->update(['id'=>intval($params['id'])],$data);
            if(!$update) ApiUtil::abort( '编辑失败');
            DB::commit();
            return ApiUtil::normal(['id'=>$params['id']]);
        }catch (\Exception $e){
            DB::rollBack();
            return ApiUtil::excep($e);
        }
    }

    public function delete(){
        $id = request()->param('id');
        $id = !empty($id)?(string)$id:'';
        if(empty($id)) return ApiUtil::normal(null, 'ID不能为空', ApiUtil::CODE_FAIL);
        $ids = explode(',', $id);
        DB::startTrans();
        try{
            $this->productService->delSkus($id);
            $this->productCategoryLinkService->delete(['product_id',$ids]);
            $delete = $this->productService->delete(['id',$ids]);
            if(!$delete) ApiUtil::abort( '删除失败');
            DB::commit();
            return ApiUtil::normal(['id'=>$ids],'删除成功');
        }catch (\Exception $e){
            DB::rollBack();
            return ApiUtil::excep($e);
        }
    }

    public function export(Excel $excel){
        $where = $this->productService->search(request()->param());
        $list = $this->productService->select($where);
        if(empty($list)) return ApiUtil::normal(null, '数据不存在', ApiUtil::CODE_FAIL);
        // 分类处理 begin
        $cates = array_unique($list->column('category_id'));
        $cate_arr = explode(',',implode(',',$cates));
        $cate_list = $this->categoryService->select([],['id','name'],['id',$cate_arr])->toArray();
        foreach ($cate_list as $cate_name) $cate_names[$cate_name['id']] = $cate_name['name'];
        /// 分类处理 end
        $list = $list->toArray();
        foreach ($list as $k=>&$item) {
            $cate_ids = explode(',',$item['category_id']);
            foreach ($cate_ids as $cate_id) $cate_name_arr[] = $cate_names[$cate_id]??null;
            $item['category_id'] = implode(',',$cate_name_arr);
            unset($cate_name_arr);
        }
        $filename = '产品列表'.date('YmdHis');
        $header = $this->productService->excelHeader();
        $download = $excel->export($list,$header,$filename);
        if(!$download) return ApiUtil::normal(null, '导出失败', ApiUtil::CODE_FAIL);
        return ApiUtil::normal(null,'导出成功');
    }

    public function import(Excel $excel){
        $header = $this->productService->excelHeader();
        $data = $excel->import();
        if(is_string($data)) return ApiUtil::normal(null, $data, ApiUtil::CODE_FAIL);
        if(!count($data)) return ApiUtil::normal(null, '导入数据为空', ApiUtil::CODE_FAIL);
        $data = array_values($data);
        $fields = array_filter(current($data));
        $cate_list = $this->categoryService->select([],['id','name'])->toArray();// 获取分类ID
        foreach ($cate_list as $cate) $cate_ids[$cate['name']] = $cate['id'];
        $inx = 0;
        $insertAll = $verifys = $nameArr = $skuArr = $cateArr = array();
        DB::startTrans();
        try{
            foreach ($data as $k => $item){
                if($k==0) continue;
                foreach ($fields as $letter => $field){
                    foreach ($header as $head){
                        if(trim($field)==$head['name']){
                            if(trim($field)=='产品名称' && !empty($item[$letter])){// 产品名称不允许重复
                                if(in_array($item[$letter],$nameArr)) return ApiUtil::abort('第'.($k+1).'行【'.$field.'】重复');
                                $nameArr[] = $item[$letter];
                            }
                            if(trim($field)=='SKU' && empty($item[$letter])) $item[$letter] = $this->productSkuService->get_product_sku();
                            if(trim($field)=='SKU' && !empty($item[$letter])){// SKU不允许重复
                                if(in_array($item[$letter],$skuArr)) return ApiUtil::abort('第'.($k+1).'行【'.$field.'】重复');
                                $skuArr[] = $item[$letter];
                            }
                            if(trim($field)=='分类' && !empty($item[$letter])){// 多个分类ID处理
                                $cates = explode(',', $item[$letter]);
                                $cate_tmp = array();
                                foreach ($cates as $cate){
                                    if(!isset($cate_ids[$cate])) return ApiUtil::abort('第'.($k+1).'行【'.$field.'】不存在');
                                    $cate_tmp[] = $cate_ids[$cate];
                                }
                                $item[$letter] = implode(',',$cate_tmp);
                            }
                            $verifys[$head['column']] = $item[$letter];
                            $insertAll[$inx][$head['column']] = $item[$letter];
                        }
                    }
                }
                $verifyData = $this->productService->verify($verifys);// 数据验证
                if(is_string($verifyData)) return ApiUtil::abort( '第'.($k+1).'行【'.$verifyData.'】');
                // 由于多分类表需要产品主键ID，故不能批量插入
                $lastId = $this->productService->insertGetId($verifyData);
                $insertCate = array();
                foreach ($cate_tmp as $cate_key => $cate_id){
                    $insertCate[$cate_key]['product_id'] = $lastId;
                    $insertCate[$cate_key]['cate_id'] = $cate_id;
                }
                $insert_cate = $this->productCategoryLinkService->insertAll($insertCate);
                if(!$insert_cate) ApiUtil::abort( '插入多分类失败');
                $inx++;
            }
            DB::commit();
            return ApiUtil::normal();
        }catch (\Exception $e){
            DB::rollBack();
            return ApiUtil::excep($e);
        }
        // dd($insertAll); 批量插入
    }
}
